﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Region
{
    public class Editors
    {

        public class EditorInfo
        {
            public String Name; // Идентификатор поля
            public String EditorType; // Тип редактора
            public Control Parent; // Родительский элемент 
            public String Caption; // Подпись
            public Int32 CaptionWidth; // Подпись 0  авторазмер
            public Int32 Width; // Размер всего элемента если 0 то автоподбор ширины
            public Object Value; // Значение
            public Object Data; // Дополнительные данные
            public SetValueCallback Callback; // обработчик изменени
            public Control EditorFrame; // Созданный редактор
            public Object Editor; // Созданный редактор
            public EditorInfo(String Name, String EditorType, Control Parent, String Caption, Int32 CaptionWidth, Object Value, Object Data, Int32 Width, SetValueCallback Callback)
            {
                this.Name = Name;
                this.EditorType = EditorType;
                this.Parent = Parent;
                this.Caption = Caption;
                this.CaptionWidth = CaptionWidth;
                this.Width = Width;
                this.Value = Value;
                this.Data = Data;
                this.Callback = Callback;
                this.EditorFrame = null;
                this.Editor = null;
            }
        }
        public static Control setEditor(ref EditorInfo EIl)
        {
            return setEditor(ref EIl, null);
        }
        public static Control setEditor(ref EditorInfo EI,ObjectFormUtil OFU)
        {
            switch (EI.EditorType)
            {
                case "Text": return setTextBox(ref EI, OFU);
                case "Tree": return setTreeBox(ref EI, OFU);
                case "Mask": return setMaskBox(ref EI, OFU);
                case "Int": return setIntBox(ref EI, OFU);
                case "DateTime": return setDateTime(ref EI, OFU);
                case "Label": return setLabel(ref EI, OFU);
                case "List": return setList(ref EI, OFU);
            }
            return null;
        }
        public delegate void SetValueCallback(String Name, Object value);
        public static Control setTextBox(ref EditorInfo EI, ObjectFormUtil OFU)
        {
            if (EI.EditorType != "Text") return null;
            if (!(EI.Value is String)) return null;
            if (EI.EditorFrame == null)
            {// Создать новый
                // Создать основной элемент
                FlowLayoutPanel p = new FlowLayoutPanel();
                p.Margin = new Padding(0);
                // Создать дочерние элементы
                Label l = new Label();
                TextBox b = new TextBox();
                p.Controls.Add(l);
                p.Controls.Add(b);
                // Назначить параметры дочерних элементов

                l.Text = EI.Caption;
                l.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                l.AutoSize = true;
                b.Text = (String)EI.Value;
                //разместить строку расположить подпись песеридини на вертикальной оси
                if (EI.CaptionWidth != 0) l.MinimumSize = l.MaximumSize = new System.Drawing.Size(EI.CaptionWidth, 0);
                l.AutoSize = true;
                l.Margin = b.Margin;

                // Пересчитать размер редактора взависимости то длины всех элементов
                if (EI.Width > 0) b.Width = EI.Width - l.Width - l.Margin.Left - l.Margin.Right - p.Margin.Left - p.Margin.Right;
                p.AutoSize = true;
                // разместить разместить основной элемент
                if (EI.Parent != null) EI.Parent.Controls.Add(p);
                // Настроить обработчик редактирования
                SetValueCallback callback = EI.Callback;
                String Name = EI.Name;
                if (callback!=null) b.TextChanged += new System.EventHandler((s, e) => { callback(Name, ((TextBox)s).Text); });
                EI.Editor = b;
                EI.EditorFrame = p;
                if (OFU!=null) OFU.AddEditor(b, EI.Name);
            }
            else
            {
                ((TextBox)EI.Editor).Text = (String)EI.Value;
            }
            return EI.EditorFrame;
        }
        public struct TreeItem { public Object ParentID, ID; public String Caption;};
        public static Control setTreeBox(ref EditorInfo EI, ObjectFormUtil OFU)
        {
            if (EI.EditorType != "Tree") return null;
            if (!(EI.Value is Object)) return null;
            if (!(EI.Data is TreeItem[])) return null;
            if (EI.EditorFrame == null)
            {// Создать новый
                // Создать основной элемент
                FlowLayoutPanel p = new FlowLayoutPanel();
                p.Margin = new Padding(0);
                // Создать дочерние элементы
                Label l = new Label();
                TreeComboBox b = new TreeComboBox();
                foreach (TreeItem i in (TreeItem[])EI.Data)
                    b.Add(i.ParentID, i.ID, i.Caption);
                b.ShowTreeList();
                b.SelectItemID(EI.Value);
                p.Controls.Add(l);
                p.Controls.Add(b);
                // Назначить параметры дочерних элементов

                l.Text = EI.Caption;
                l.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                l.AutoSize = true;
                //b.Text = (String)EI.Value;
                //разместить строку расположить подпись песеридини на вертикальной оси
                if (EI.CaptionWidth != 0) l.MinimumSize = l.MaximumSize = new System.Drawing.Size(EI.CaptionWidth, 0);
                l.AutoSize = true;
                l.Margin = b.Margin;

                // Пересчитать размер редактора взависимости то длины всех элементов
                if (EI.Width > 0) b.Width = EI.Width - l.Width - l.Margin.Left - l.Margin.Right - p.Margin.Left - p.Margin.Right;
                p.AutoSize = true;
                // разместить разместить основной элемент
                if (EI.Parent != null) EI.Parent.Controls.Add(p);
                // Настроить обработчик редактирования
                SetValueCallback callback = EI.Callback;
                String Name = EI.Name;
                if (callback != null) b.ItemChange += new System.EventHandler((s, e) => { callback(Name, ((TreeComboBox)s).SelectItemID()); });                
                EI.Editor = b;
                EI.EditorFrame = p;                
                if (OFU != null) OFU.AddEditor(b, EI.Name);
            }
            else
            {
                ((TreeComboBox)EI.Editor).SelectItemID(EI.Value);
            }
            return EI.EditorFrame;
        }
        public static Control setMaskBox(ref EditorInfo EI, ObjectFormUtil OFU)
        {
            if (EI.EditorType != "Mask") return null;
            if (!(EI.Value is String)) return null;
            if (!(EI.Data is String)) return null;
            if (EI.EditorFrame == null)
            {// Создать новый
                // Создать основной элемент
                FlowLayoutPanel p = new FlowLayoutPanel();
                p.Margin = new Padding(0);
                // Создать дочерние элементы
                Label l = new Label();
                MaskedTextBox b = new MaskedTextBox();
                p.Controls.Add(l);
                p.Controls.Add(b);
                // Назначить параметры дочерних элементов

                l.Text = EI.Caption;
                l.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                l.AutoSize = true;
                b.Mask = (String)EI.Data;
                b.Text = (String)EI.Value;
                //разместить строку расположить подпись песеридини на вертикальной оси
                if (EI.CaptionWidth != 0) l.MinimumSize = l.MaximumSize = new System.Drawing.Size(EI.CaptionWidth, 0);
                l.AutoSize = true;
                l.Margin = b.Margin;

                // Пересчитать размер редактора взависимости то длины всех элементов
                if (EI.Width > 0) b.Width = EI.Width - l.Width - l.Margin.Left - l.Margin.Right - p.Margin.Left - p.Margin.Right;
                p.AutoSize = true;
                // разместить разместить основной элемент
                if (EI.Parent != null) EI.Parent.Controls.Add(p);
                // Настроить обработчик редактирования
                SetValueCallback callback = EI.Callback;
                String Name = EI.Name;
                if (callback != null) b.TextChanged += new System.EventHandler((s, e) => { callback(Name, ((MaskedTextBox)s).Text); });
                EI.Editor = b;
                EI.EditorFrame = p;
                if (OFU != null) OFU.AddEditor(b, EI.Name);
            }
            else
            {
                ((MaskedTextBox)EI.Editor).Text = (String)EI.Value;
            }
            return EI.EditorFrame;
        }
        public static Control setIntBox(ref EditorInfo EI, ObjectFormUtil OFU)
        {
            if (EI.EditorType != "Int") return null;
            if (!(EI.Value is Int32)) return null;
            if (EI.EditorFrame == null)
            {// Создать новый
                // Создать основной элемент
                FlowLayoutPanel p = new FlowLayoutPanel();
                p.Margin = new Padding(0);
                // Создать дочерние элементы
                Label l = new Label();
                NumericUpDown b = new NumericUpDown();
                p.Controls.Add(l);
                p.Controls.Add(b);
                // Назначить параметры дочерних элементов
                l.Text = EI.Caption;
                l.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                b.Maximum = Int32.MaxValue;
                b.Minimum = Int32.MinValue;
                b.Value = (Int32)EI.Value;
                //разместить строку расположить подпись песеридини на вертикальной оси
                if (EI.CaptionWidth != 0) l.MinimumSize = l.MaximumSize = new System.Drawing.Size(EI.CaptionWidth, 0);
                l.AutoSize = true;
                l.Margin = b.Margin;

                // Пересчитать размер редактора взависимости то длины всех элементов
                if (EI.Width > 0) b.Width = EI.Width - l.Width - l.Margin.Left - l.Margin.Right - p.Margin.Left - p.Margin.Right;
                p.AutoSize = true;
                // разместить разместить основной элемент
                if (EI.Parent != null) EI.Parent.Controls.Add(p);
                // Настроить обработчик редактирования
                SetValueCallback callback = EI.Callback;
                String Name = EI.Name;
                if (callback != null) b.TextChanged += new System.EventHandler((s, e) => { callback(Name, (Int32)((NumericUpDown)s).Value); });
                EI.Editor = b;
                EI.EditorFrame = p;
                if (OFU != null) OFU.AddEditor(b, EI.Name);
            }
            else
            {
                ((NumericUpDown)EI.Editor).Value = (Int32)EI.Value;
            }
            return EI.EditorFrame;
        }
        public static Control setDateTime(ref EditorInfo EI, ObjectFormUtil OFU)
        {
            if (EI.EditorType != "DateTime") return null;
            if (!(EI.Value is DateTime)) return null;
            if (EI.EditorFrame == null)
            {// Создать новый
                // Создать основной элемент
                FlowLayoutPanel p = new FlowLayoutPanel();
                p.Margin = new Padding(0);
                // Создать дочерние элементы
                Label l = new Label();
                DateTimePicker b = new DateTimePicker();
                p.Controls.Add(l);
                p.Controls.Add(b);
                // Назначить параметры дочерних элементов
                l.Text = EI.Caption;
                l.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                l.AutoSize = true;
                b.ShowCheckBox = true;
                b.Width = 160;
                if ((DateTime)EI.Value == new DateTime(1970, 1, 1) || EI.Value == null)
                {
                    b.Value = DateTime.Now;
                    b.Checked = false;
                }
                else
                {
                    b.Value = (DateTime)EI.Value;
                    b.Checked = true;
                }
                //разместить строку расположить подпись песеридини на вертикальной оси
                if (EI.CaptionWidth != 0) l.MinimumSize = l.MaximumSize = new System.Drawing.Size(EI.CaptionWidth, 0);
                l.AutoSize = true;
                l.Margin = b.Margin;
                // Пересчитать размер редактора взависимости то длины всех элементов
                if (EI.Width > 0) b.Width = EI.Width - l.Width - l.Margin.Left - l.Margin.Right - p.Margin.Left - p.Margin.Right;
                p.AutoSize = true;
                // разместить разместить основной элемент
                if (EI.Parent != null) EI.Parent.Controls.Add(p);
                // Настроить обработчик редактирования
                SetValueCallback callback = EI.Callback;
                String Name = EI.Name;
                if (callback != null) b.TextChanged += new System.EventHandler((s, e) => { DateTimePicker DTP = (DateTimePicker)s; callback(Name, (DTP.Checked) ? ((Object)DTP.Value) : (null)); });
                EI.Editor = b;
                EI.EditorFrame = p;
                if (OFU != null) OFU.AddEditor(b, EI.Name);
            }
            else
            {
                if ((DateTime)EI.Value == new DateTime(1970, 1, 1) || EI.Value == null)
                {
                    ((DateTimePicker)EI.Editor).Value = DateTime.Now;
                    ((DateTimePicker)EI.Editor).Checked = false;
                }
                else
                {
                    ((DateTimePicker)EI.Editor).Value = (DateTime)EI.Value;
                    ((DateTimePicker)EI.Editor).Checked = true;
                }
            }
            return EI.EditorFrame;
        }
        public static Control setLabel(ref EditorInfo EI, ObjectFormUtil OFU)
        {
            if (EI.EditorType != "Label") return null;
            if (EI.EditorFrame == null)
            {// Создать новый
                // Создать основной элемент
                FlowLayoutPanel p = new FlowLayoutPanel();
                p.Margin = new Padding(0);
                // Создать дочерние элементы
                Label l = new Label();
                p.Controls.Add(l);
                // Назначить параметры дочерних элементов
                l.Text = EI.Caption;
                l.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                l.AutoSize = true;
                //разместить строку расположить подпись песеридини на вертикальной оси
                l.AutoSize = false; l.Width = 200;
                Int32 W = l.Width;
                l.AutoSize = false;
                l.Width = W;
                // Пересчитать размер редактора взависимости то длины всех элементов
                if (EI.Width == -1)
                {
                    p.Width = EI.Parent.Width - 20;
                    l.Width = p.Width - l.Margin.Left - l.Margin.Right;
                }
                else if (EI.Width == 0) { }
                else { l.Width = EI.Width; }
                p.AutoSize = true;
                // разместить разместить основной элемент
                if (EI.Parent != null) EI.Parent.Controls.Add(p);
                EI.EditorFrame = p;
            }
            return EI.EditorFrame;
        }
        public static Control setList(ref EditorInfo EI, ObjectFormUtil OFU)
        {
            if (EI.EditorType != "List") return null;
            if (!(EI.Value is Int32)) return null;
            if (!(EI.Data is Dictionary<Int32, String>)) return null;
            if (EI.EditorFrame == null)
            {// Создать новый
                // Создать основной элемент
                FlowLayoutPanel p = new FlowLayoutPanel();
                p.Margin = new Padding(0);
                // Создать дочерние элементы
                Label l = new Label();
                ComboBox b = new ComboBox();
                p.Controls.Add(l);
                p.Controls.Add(b);
                // Назначить параметры дочерних элементов
                l.Text = EI.Caption;
                l.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                l.AutoSize = true;
                b.DropDownStyle = ComboBoxStyle.DropDownList;
                Dictionary<Int32, String> List = (Dictionary<Int32, String>)EI.Data;
                foreach (KeyValuePair<Int32, String> i in List)
                {
                    b.Items.Add(new Utils.ListItemValue(i.Value, i.Key));
                }
                b.SelectedItem = new Utils.ListItemValue(List[(Int32)EI.Value], (Int32)EI.Value);
                //b.Text = (Int32)EI.Value;

                //разместить строку расположить подпись песеридини на вертикальной оси
                if (EI.CaptionWidth != 0) l.MinimumSize = l.MaximumSize = new System.Drawing.Size(EI.CaptionWidth, 0);
                l.AutoSize = true;
                l.Margin = b.Margin;
                // Пересчитать размер редактора взависимости то длины всех элементов
                if (EI.Width > 0) b.Width = EI.Width - l.Width - l.Margin.Left - l.Margin.Right - p.Margin.Left - p.Margin.Right;
                p.AutoSize = true;
                // разместить разместить основной элемент
                if (EI.Parent != null) EI.Parent.Controls.Add(p);
                // Настроить обработчик редактирования
                SetValueCallback callback = EI.Callback;
                String Name = EI.Name;
                if (callback != null) b.SelectedValueChanged += new System.EventHandler((s, e) => { callback(Name, ((Utils.ListItemValue)((ComboBox)s).SelectedItem).Value); });
                EI.Editor = b;
                EI.EditorFrame = p;
                if (OFU != null) OFU.AddEditor(b, EI.Name);
            }
            else
            {
                Dictionary<Int32, String> List = (Dictionary<Int32, String>)EI.Data;
                ((ComboBox)EI.Editor).SelectedItem = new Utils.ListItemValue(List[(Int32)EI.Value], (Int32)EI.Value);
            }
            return EI.EditorFrame;
        }
    }
}